/*
 * This file is part of Grocy Android.
 *
 * Grocy Android is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Grocy Android is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Grocy Android. If not, see http://www.gnu.org/licenses/.
 *
 * Copyright (c) 2020-2024 by Patrick Zedler and Dominic Zedler
 * Copyright (c) 2024-2025 by Patrick Zedler
 */

package xyz.zedler.patrick.grocy.form;

import android.app.Application;
import android.content.SharedPreferences;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Transformations;
import androidx.preference.PreferenceManager;
import java.util.List;
import xyz.zedler.patrick.grocy.model.Location;
import xyz.zedler.patrick.grocy.model.Product;
import xyz.zedler.patrick.grocy.model.Store;
import xyz.zedler.patrick.grocy.util.NumUtil;
import xyz.zedler.patrick.grocy.util.VersionUtil;

public class FormDataMasterProductCatLocation {

  private final MutableLiveData<Boolean> displayHelpLive;
  private final MutableLiveData<List<Location>> locationsLive;
  private final MutableLiveData<Location> locationLive;
  private final LiveData<String> locationNameLive;
  private final LiveData<Boolean> locationErrorLive;
  private final MutableLiveData<Location> locationConsumeLive;
  private final LiveData<String> locationConsumeNameLive;
  private final MutableLiveData<Boolean> moveOnOpenLive;
  private final MutableLiveData<Boolean> moveOnOpenDisabledLive;
  private final MutableLiveData<List<Store>> storesLive;
  private final MutableLiveData<Store> storeLive;
  private final LiveData<String> storeNameLive;

  private final boolean showMoveOnOpen;
  private boolean filledWithProduct;

  public FormDataMasterProductCatLocation(Application application, boolean beginnerMode) {
    displayHelpLive = new MutableLiveData<>(beginnerMode);
    locationsLive = new MutableLiveData<>();
    locationLive = new MutableLiveData<>();
    locationNameLive = Transformations.map(
        locationLive,
        location -> location != null ? location.getName() : null
    );
    //noinspection Convert2MethodRef
    locationErrorLive = Transformations.map(
        locationLive,
        location -> location == null
    );
    locationConsumeLive = new MutableLiveData<>();
    locationConsumeNameLive = Transformations.map(
        locationConsumeLive,
        location -> location != null ? location.getName() : null
    );
    moveOnOpenLive = new MutableLiveData<>(false);
    moveOnOpenDisabledLive = new MutableLiveData<>(false);
    storesLive = new MutableLiveData<>();
    storeLive = new MutableLiveData<>();
    storeNameLive = Transformations.map(
        storeLive,
        store -> store != null ? store.getName() : null
    );

    SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(application);
    showMoveOnOpen = VersionUtil.isGrocyServerMin330(sharedPrefs);
    filledWithProduct = false;
  }

  public MutableLiveData<Boolean> getDisplayHelpLive() {
    return displayHelpLive;
  }

  public void toggleDisplayHelpLive() {
    assert displayHelpLive.getValue() != null;
    displayHelpLive.setValue(!displayHelpLive.getValue());
  }

  public MutableLiveData<List<Location>> getLocationsLive() {
    return locationsLive;
  }

  public MutableLiveData<Location> getLocationLive() {
    return locationLive;
  }

  public LiveData<String> getLocationNameLive() {
    return locationNameLive;
  }

  public LiveData<Boolean> getLocationErrorLive() {
    return locationErrorLive;
  }

  public MutableLiveData<Location> getLocationConsumeLive() {
    return locationConsumeLive;
  }

  public LiveData<String> getLocationConsumeNameLive() {
    return locationConsumeNameLive;
  }

  public boolean isShowMoveOnOpen() {
    return showMoveOnOpen;
  }

  public MutableLiveData<Boolean> getMoveOnOpenLive() {
    return moveOnOpenLive;
  }

  public void toggleMoveOnOpenLive() {
    assert moveOnOpenLive.getValue() != null;
    moveOnOpenLive.setValue(!moveOnOpenLive.getValue());
  }

  public MutableLiveData<Boolean> getMoveOnOpenDisabledLive() {
    return moveOnOpenDisabledLive;
  }

  public void disableMoveOnOpenIfNecessary() {
    moveOnOpenDisabledLive.setValue(locationConsumeLive.getValue() == null);
    assert moveOnOpenDisabledLive.getValue() != null;
    if (moveOnOpenDisabledLive.getValue()) {
      moveOnOpenLive.setValue(false);
    }
  }

  public MutableLiveData<List<Store>> getStoresLive() {
    return storesLive;
  }

  public MutableLiveData<Store> getStoreLive() {
    return storeLive;
  }

  public LiveData<String> getStoreNameLive() {
    return storeNameLive;
  }

  private Location getLocationFromId(String id) {
    if (locationsLive.getValue() == null || !NumUtil.isStringInt(id)) {
      return null;
    }
    int idInt = Integer.parseInt(id);
    for (Location location : locationsLive.getValue()) {
      if (location.getId() == idInt) {
        return location;
      }
    }
    return null;
  }

  private Store getStoreFromId(String id) {
    if (storesLive.getValue() == null || !NumUtil.isStringInt(id)) {
      return null;
    }
    int idInt = Integer.parseInt(id);
    for (Store store : storesLive.getValue()) {
      if (store.getId() == idInt) {
        return store;
      }
    }
    return null;
  }

  public boolean isFormValid() {
    return locationLive.getValue() != null;
  }

  public static boolean isFormInvalid(@Nullable Product product) {
    if (product == null) {
      return true;
    }
    boolean valid = product.getLocationId() != null && !product.getLocationId().isEmpty();
    return !valid;
  }

  public Product fillProduct(@NonNull Product product) {
    if (!isFormValid()) {
      if (locationLive.getValue() == null && NumUtil.isStringInt(product.getLocationId())) {
        product.setLocationId(null);
      }
      if (locationConsumeLive.getValue() == null
          && NumUtil.isStringInt(product.getDefaultConsumeLocationId())) {
        product.setDefaultConsumeLocationId(null);
      }
      if (storeLive.getValue() == null && NumUtil.isStringInt(product.getStoreId())) {
        product.setStoreId(null);
      }
      return product;
    }
    Location location = locationLive.getValue();
    Location locationConsume = locationConsumeLive.getValue();
    Store store = storeLive.getValue();
    product.setLocationId(location != null ? String.valueOf(location.getId()) : null);
    product.setDefaultConsumeLocationId(locationConsume != null
        ? String.valueOf(locationConsume.getId()) : null);
    assert moveOnOpenLive.getValue() != null;
    assert moveOnOpenDisabledLive.getValue() != null;
    product.setMoveOnOpenBoolean(!moveOnOpenDisabledLive.getValue()
        ? moveOnOpenLive.getValue() : false);
    product.setStoreId(store != null ? String.valueOf(store.getId()) : null);
    return product;
  }

  public void fillWithProductIfNecessary(Product product) {
    if (filledWithProduct || product == null) {
      return;
    }

    locationLive.setValue(getLocationFromId(product.getLocationId()));
    locationConsumeLive.setValue(getLocationFromId(product.getDefaultConsumeLocationId()));
    moveOnOpenLive.setValue(product.getMoveOnOpenBoolean());
    moveOnOpenDisabledLive.setValue(locationLive.getValue()
        == locationConsumeLive.getValue() || locationConsumeLive.getValue() == null);
    storeLive.setValue(getStoreFromId(product.getStoreId()));
    filledWithProduct = true;
  }
}
